package com.imooc.autoconfigure;

import com.imooc.advisor.DynamicDataSourceAdvisor;
import com.imooc.annotation.DDS;
import com.imooc.annotation.DDSTransactional;
import com.imooc.datasource.DynamicRoutingDataSource;
import com.imooc.init.DataSourceInit;
import com.imooc.init.DecryptDataSourceInit;
import com.imooc.interceptor.DynamicDataSourceInterceptor;
import com.imooc.interceptor.DynamicTransactionalInterceptor;
import com.imooc.propterties.DynamicDataSourceProperty;
import com.imooc.provider.DynamicDataSourceProvider;
import com.imooc.provider.YamlDynamicDataSourceProvider;
import com.imooc.support.DataSourceClassResolver;
import org.springframework.aop.Advisor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.Order;

import javax.sql.DataSource;
import java.util.List;

/**
 * @Author Tim
 * @Description:
 * @Version 1.0
 */
@Configuration
@EnableConfigurationProperties(value = DynamicDataSourceProperty.class)
@Import(value = {DynamicDataSourceClassResolverAutoConfiguration.class, DynamicDataSourceCreatorAutoConfiguration.class})
@ConditionalOnProperty(prefix = DynamicDataSourceProperty.PREFIX, name="enable", havingValue = "true", matchIfMissing = true)
@AutoConfigureBefore(name = "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration")
public class DynamicDataSourceAutoConfiguration {

    private final DynamicDataSourceProperty dataSourceProperty;

    public DynamicDataSourceAutoConfiguration(DynamicDataSourceProperty dataSourceProperty) {
        this.dataSourceProperty = dataSourceProperty;
    }

    @Order(0)
    @Bean
    public YamlDynamicDataSourceProvider yamlDynamicDataSourceProvider() {
        return new YamlDynamicDataSourceProvider(dataSourceProperty.getDataSource());
    }

    //当前不存在其它datasource才去装配
    @ConditionalOnMissingBean
    @Bean
    @Primary
    public DataSource dataSource(List<DynamicDataSourceProvider> providers) {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource(providers);
        dataSource.setPrimary(this.dataSourceProperty.getPrimary());
        return dataSource;
    }

    @Bean
    public DataSourceInit dataSourceInit() {
        return new DecryptDataSourceInit();
    }

    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @Bean
    public Advisor dynamicDataSourceAnnocationAdvisor(List<DataSourceClassResolver> resolvers) {
        DynamicDataSourceInterceptor advice = new DynamicDataSourceInterceptor(resolvers);
        DynamicDataSourceAdvisor advisor = new DynamicDataSourceAdvisor(advice, DDS.class);
        return advisor;
    }

    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @Bean
    public Advisor dynamicTransactionDataSourceAnnocationAdvisor() {
        DynamicTransactionalInterceptor advice = new DynamicTransactionalInterceptor();
        DynamicDataSourceAdvisor advisor = new DynamicDataSourceAdvisor(advice, DDSTransactional.class);
        return advisor;
    }
}
